package com.nescafe.nescafepromo.command.user;

import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Transaction;
import com.nescafe.nescafepromo.command.Command;
import com.nescafe.nescafepromo.command.CommandException;
import com.nescafe.nescafepromo.entity.EntityType;
import com.nescafe.nescafepromo.entity.ExtraPoint;
import com.nescafe.nescafepromo.entity.TotalPoints;
import com.nescafe.nescafepromo.model.NPRequest;
import com.nescafe.nescafepromo.model.NPResponse;

public class ShoutOut implements Command {

	@Override
	public NPResponse execute(NPRequest req) throws CommandException {
		NPResponse res = null;
		Transaction txn = null;
		try {
			String fbID = req.getParam("fb_id");
			String accessToken = req.getParam("access_token");
			String message = "I just earned an extra point!";

			if (fbID != null && accessToken != null) {
				// Create query string
				StringBuilder queryString = new StringBuilder();
				queryString.append("message=" + URLEncoder.encode(message, "UTF-8"));
				queryString.append("&access_token=" + URLEncoder.encode(accessToken, "UTF-8"));
				// queryString.append("&picture=" +
				// URLEncoder.encode("http://koffeejunkie.com/commons/images/char-logo.png",
				// "UTF-8"));
				queryString.append("&link=" + URLEncoder.encode("http://apps.facebook.com/nescafepromo", "UTF-8"));
				queryString.append("&name=The Challenge");
				queryString.append("&caption=Join TheChallenge");
				queryString.append("&description=Insert description here ");

				// Make connection
				URL url = new URL("https://graph.facebook.com/" + fbID + "/feed");
				URLConnection urlConnection = url.openConnection();
				urlConnection.setDoOutput(true);
				OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());
				out.write(queryString.toString());
				out.flush();
				urlConnection.getInputStream();
				out.close();

				String email = req.getParam("email");
				Key participantKey = EntityType.PARTICIPANT.getKey(email);

				DatastoreService ds = DatastoreServiceFactory.getDatastoreService();

				// check if participant has purchased something
				Query q = new Query(EntityType.PURCHASE.getKind());
				q.setAncestor(participantKey);
				if (ds.prepare(q).countEntities(FetchOptions.Builder.withLimit(1)) > 0) {
					Date now = new Date();
					DateFormat df = new SimpleDateFormat("yyyyMMdd");
					String nowStr = df.format(now);
					int date = Integer.parseInt(nowStr);

					// check if participant has already performed shout out for
					// today
					Key extraPointKey = EntityType.EXTRA_POINT.getKey(participantKey, date);

					try {
						ds.get(extraPointKey);
						throw new CommandException("You can only claim one shoutout point per day.");
					} catch (EntityNotFoundException notFoundEx) {
						ArrayList<Entity> entities = new ArrayList<Entity>();
						txn = ds.beginTransaction();
						ExtraPoint extraPoint = new ExtraPoint(date, participantKey);
						entities.add(extraPoint.toEntity());

						// update total points
						Key totalPointsKey = EntityType.TOTAL_POINTS.getKey(participantKey, email);
						TotalPoints totalPoints = new TotalPoints(ds.get(totalPointsKey));

						long newTotal = totalPoints.getTotalPonts() + 1;
						totalPoints.setTotalPonts(newTotal);
						entities.add(totalPoints.toEntity());

						ds.put(entities);
						txn.commit();
					}
				}
			}

			res = new NPResponse("You have just earned one point! Purchase more Nescafe Products now to earn more points!");
		} catch (Exception e) {
			throw new CommandException(e.getMessage());
		} finally {
			if (txn != null && txn.isActive()) {
				txn.rollback();
			}
		}
		return res;
	}

}
